var Game = function(controller)
{
    this.rules          = Rules;
    this.board          = this.createBoard();
    this.players        = this.createGamePlayers();
    this.currentPlayer  = this.getStartingPlayer();
    this.winnerPlayer   = null;
    this.controller     = controller;
    this.lastMadeMove   = null;
    this.winningStroke  = null; 
}

Game.prototype.createBoard = function()
{
    return new Board();
}

Game.prototype.createGamePlayers = function()
{
    return this.rules.createGamePlayers();
}

Game.prototype.getPlayers = function()
{
    return this.players;
}

Game.prototype.getStartingPlayer = function()
{
    return this.getPlayers() !== undefined && this.getPlayers() !== null ? (this.getPlayers())[0] : null;
}

Game.prototype.getBoard = function()
{
    return this.board;
}

Game.prototype.start = function()
{
    this.board.reInitialize();
    this.currentPlayer  = this.getStartingPlayer();
    this.winnerPlayer   = null;    
}

Game.prototype.stop = function()
{
    this.currentPlayer = null;
}

Game.prototype.isStopped = function()
{
    return this.currentPlayer === null;
}
    
Game.prototype.getCurrentPlayer = function()
{
    return this.currentPlayer;
}

Game.prototype.getWinnerPlayer = function()
{
    return this.winnerPlayer;
}

Game.prototype.createLocation = function(location)
{
    return new Location(location);
}

Game.prototype.createMove = function(player, board, location)
{
    return new Move(player, board, location);
}
    
Game.prototype.makeMove = function(location)
{
    if (this.currentPlayer === null) 
        throw new Error("There is no current player to make a move.");

    var _location   = this.createLocation(location);
    var move        = this.createMove(this.currentPlayer, this.getBoard(), _location);

    if (this.rules.isMoveLegal(move) == false)
    {
        this.controller.notifyIllegalMove();
    }
    else
    {
        this.board.makeMove(move);
        this.lastMadeMove = move;
        this.controller.notifyGameMove(location); // TODO: don't pass in a parameter, but get it via the getLastMove()

        if (this.rules.isGameDraw(this.board))
        {
            this.winnerPlayer = null;
            this.stop();
            this.controller.notifyGameDraw();
        }
        else if (this.rules.isGameWin(this.board))
        {
            this.winningStroke = this.rules.getWinningStroke();
            this.winnerPlayer = this.currentPlayer;
            this.stop();
            this.controller.notifyGameWin();
        }
        else
        {
            this.currentPlayer = this.rules.getNextPlayer(this.players, this.currentPlayer);
            this.controller.notifyCurrentPlayerChanged();
            /*
            if (mCurrentPlayer instanceof AIPlayer)
            {
                AIPlayer aiPlayer = (AIPlayer)mCurrentPlayer;
                aiPlayer.setGame(this);
                Thread aiPlayerThread = new Thread(aiPlayer); 
                aiPlayerThread.start();
            }
            */
        }
    }    
}